#include "mainwindow.h"


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    projReady=false;
    calibReady=false;
    videoReady=false;

    camResolution=720;  //default to 1280x720
    numCams=2; //default using 2 cameras
    ui->setupUi(this);
    setWindowTitle("Slosh Test");

    calibCams=0;    //initialize to null
    regTargets=0;   //initialize to null

    //label formatting
    redFont="<font color=\"red\">";
    greenFont="<font color=\"green\">";
    blueFont="<font color=\"blue\">";
    endFont="</font>";



}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_CameraCalibrate_clicked()
{
    if(!projReady)
        QMessageBox::information(this, "Project Not Set","Complete Project Settings First");
    else {
        //Create the dialog
        //        dialogCalibCams calibCams(this);
        if(!calibCams) {  //make sure dialog is not already open
            calibCams= new dialogCalibCams(this);
            connect(calibCams, SIGNAL(finished(int)), SLOT(CheckCalibReady())); //when dialog closes check to see if all req'd info is there
            calibCams->resHeight=resHeight;
            calibCams->resWidth=resWidth;
            calibCams->projdir=projDir;
            calibCams->show();
            calibCams->raise();
        }// else just ignore the button push

    }
}


void MainWindow::on_pushButton_ProjSettings_clicked()
{
    //Create the dialog
    DialogProjectSettings proj(this);

    //Set Current Values
    if (!projDir.isEmpty())
        proj.projectDirectory=projDir;
    if (!eventName.isEmpty())
        proj.eventName=eventName;
    if (!testDesc.isEmpty())
        proj.testDesc=testDesc;
    if(camResolution)
        proj.camResolution=camResolution;
    proj.numCams=numCams;

    proj.setCurrentValues();

    //launch the dialog & test for acceptance
    if(proj.exec() == QDialog::Accepted) {

        projDir=proj.projectDirectory;
        eventName=proj.eventName;
        testDesc=proj.testDesc;
        camResolution=proj.camResolution;

        //set resolution
        resHeight=camResolution;
        switch(camResolution){
        case 480: resWidth=640;break;
        case 720: resWidth=1280;break;
        case 1080: resWidth=1920;break;
        }

        //make sure all are set
        QString status;
        if(!projDir.isEmpty() )
            status= greenFont + "Project Folder: "+ endFont+ blueFont+ projDir +endFont+"<br>";
        else
            status= redFont + "Project Folder: NOT SET" + endFont+"<br>";

        if(!eventName.isEmpty())
            status+= greenFont + "Event Folder Name: "+ endFont+ blueFont+ QFileInfo(eventName).fileName() +endFont+"<br>";
        else
            status+=redFont+"Event Folder Name: NOT SET" + endFont +"<br>";
        if(!testDesc.isEmpty() && testDesc != "Test Details")
            status+=greenFont+"Event Description: "+endFont+blueFont+ QString(testDesc).replace('\n',"<br>")+endFont +"<br>";
        else
            status+=redFont+"Event Description: NOT SET"+endFont+"<br>";

        status+=greenFont+" Resolution: " + endFont+ blueFont+ QString::number(resWidth) + "x" + QString::number(resHeight)+endFont;

        ui->label_ProjectSettings->setText(status);

            //ADD Project & Event Settings Write to File Here
        if(!projDir.isEmpty() && !eventName.isEmpty() && !testDesc.isEmpty() && testDesc != "Test Details")
            projReady=true;
        else projReady=false;

        // Check existing if camera calib exists
        calibReady=CheckCalibReady();

        // Check if registration target data exists
        targetsReady=CheckTargetsReady();

        // Check if video files exist
        videoReady=CheckVideoReady();

        // check if processed results exist
        resultsReady=checkResultsReady();
    }



}

void MainWindow::on_pushButton_RefTargets_clicked()
{
    // check if we are ready
    if(!projReady)
        QMessageBox::information(this, "Project/Event Not Set","Complete Project & Event Settings First");
    //call Reference target sub program
    else {
        if(!regTargets) {//make sure the dialog hasn't already been opened
            regTargets = new dialogRegistrationTargets(this);
            connect(regTargets, SIGNAL(finished(int)), SLOT(CheckTargetsReady())); //when dialog closes call to check & clean up

            //initialize
            regTargets->setAttribute(Qt::WA_DeleteOnClose); //have the dialog clean up when it gets closed
            regTargets->projName=projDir;
            regTargets->init(eventName);
            regTargets->resWidth=resWidth;
            regTargets->resHeight=resHeight;


            regTargets->show();  //using show (not exec()) here for modeless behavior so OpenCV window doesn't get focus stolen by Qt
            regTargets->raise();
        } //else just ignore the button push
    }

}


void MainWindow::on_pushButton_TestEvent_clicked()
{
    // check if we are ready
    if( !projReady + !CheckTargetsReady() )
        QMessageBox::information(this, "Project &/or Targets Not Set","Complete Project & Target Settings First");
    //call Reference target sub program
    else {
    DialogTestEventCapture testcap(this);

    //initialize
    testcap.resWidth=resWidth;
    testcap.resHeight=resHeight;
    testcap.init(eventName);

    testcap.exec();
    CheckVideoReady();
    }
}

void MainWindow::on_pushButton_ReviewResults_clicked()
{
    //add check if we are ready
    if(!checkResultsReady())
        QMessageBox::information(this, "Results Not available.", "Complete Processing First.");
    else
    {
        dlgVis = new DialogVisualize(this);
        dlgVis->setAttribute(Qt::WA_DeleteOnClose);
        dlgVis->setWindowFlags(Qt::Window);// min/max buttons
        dlgVis->eventName=eventName;  //share the event name with the dialog object
        dlgVis->show();
        dlgVis->raise();
    }

}

void MainWindow::on_pushButton_ProcessVideo_clicked()
{
    // check if we are ready
    if(!projReady + !CheckCalibReady() + !CheckTargetsReady() + !CheckVideoReady())
        QMessageBox::information(this, "Items Missing","Need Project/Event Set, Calibration Complete, Event Targets Set, and Video Files First.");
    else{

    DialogProcessVideo process(this);
    process.eventName=eventName;
    process.projName=projDir;
    process.camRes=QString::number(resWidth)+"x"+QString::number(resHeight);
    process.init();
    process.setWindowFlags(Qt::Window); //gives it max/min & close buttons
    process.exec();
    }
}


bool MainWindow::CheckCalibReady(){

    if(calibCams) {
        calibCams->deleteLater();  //clean up and release memory
        calibCams =0; //set so we can re-enter the dilog again
    }


    int testval=0;
    for(int i=0;i<2;i++) //check for both cameras
    {
        //reset the camera intrinsic matrices
        matCam[i].release();
        matDist[i].release();

        //construct filename from project settings
        std::ostringstream filename;
        filename << qPrintable(projDir) << "/Cam" << i << "_"
                 << resWidth << "x" << resHeight << ".yml";
        std::string str=filename.str();
        cv::FileStorage fs(str, cv::FileStorage::READ); // Read the settings
        if(fs.isOpened()){
            fs["camera_matrix"] >> matCam[i] ;
            fs["distortion_coefficients"] >> matDist[i];
            fs.release();

            if(!matCam[i].empty() && !matDist[i].empty())
            testval+= (i+1);
        }
    }
    QString status;
    switch(testval) {
    case 1: // cam0 is ready, but cam1 is not
        status= greenFont+"Cam0: Calibrated"+endFont+ redFont+ "Cam1: NOT Calibrated"+endFont;
        break;
    case 2: // cam1 is ready, but cam0 is not
        status= redFont+"Cam1: NOT Calibrated"+endFont+greenFont+ "Cam0: Calibrated"+endFont;
        break;
    case 3: // both cams ready
        status=greenFont+"Calibration Ready"+endFont;
        break;
    default: //neither ready
        status=redFont+"CALIBRATION NOT READY"+endFont;
    }
    ui->label_CalibCam->setText(status);


    if (testval==3)
        return true;
    else
        return false;
}

bool MainWindow::CheckTargetsReady(){

    if (regTargets) {
        regTargets->deleteLater();  //Clean up
        regTargets=0; //set so we can re-open the dialog if button is pushed again
    }


    bool targProjReady=false;
    bool targEventReady=false;

    //First check if a project target file exists
    //construct filename from project settings
    QString filename(projDir+ "/targetsProject.yml");
    cv::FileStorage fs(filename.toStdString(), cv::FileStorage::READ); // Read the settings
    if(fs.isOpened()){
        fs["World_Targets"] >> targetWorld;
        fs.release();
        if(!targetWorld.empty())
        targProjReady = true;
    }
    fs.release();

    filename=eventName+"/RegistrationTargets/targets.yml";
    fs.open(filename.toStdString(),cv::FileStorage::READ);
    if(fs.isOpened()){
        fs["Cam0_Targets"] >> targetCam0 ;
        fs["Cam1_Targets"] >> targetCam1;
        fs["World_Targets"] >> targetWorld;
        fs.release();

        if(!targetCam0.empty() && !targetCam1.empty()&& !targetWorld.empty())
        targEventReady = true;
    }


    //update labels & return
    QString status;
    if(targEventReady)
        status += greenFont + "Event Targets: Set" + endFont + "<br>";
    else
        status += redFont + "Event Targets: NOT SET" + endFont + "<br>";
    if(targProjReady)
        status += "(Project targets available)";
    ui->label_RefTargets->setText(status);
    if(targProjReady)return true;
    else return false;

}

bool MainWindow::CheckVideoReady()
{
    int videoReady=0;
    for(int i=0;i<2;i++) {
        if(QFile(eventName + "/VideoFiles/Cam" + QString::number(i)
                 + ".avi").exists()) videoReady +=i+1;
    }

    QString status;
    if(videoReady==3)
        status += greenFont  + "Video Files Available." + endFont + "<br>";
    else
        status += redFont + "NO Video Files." + endFont +"<br>";

    ui->label_TestEvent->setText(status);

    if(videoReady==3) return true;
    else return false;

}

bool MainWindow::checkResultsReady()
{
    int lineProcReady=0, triang3DReady=0;
    for(int i=0;i<2;i++) {
        if(QFile(eventName + "/ProcessedResults/cam" + QString::number(i)
                 + "_lineProcessingResult.yml.gz").exists()) lineProcReady +=i+1;
    }
    for(int i=0;i<2;i++) {
        if(QFile(eventName + "/ProcessedResults/cam" + QString::number(i)
                 + "_3Dpts.yml.gz").exists()) triang3DReady +=i+1;
    }

    QString status;
    if(lineProcReady==3)
        status += greenFont  + "  Line Processing Results Available." + endFont + "<br>";
    else
        status += redFont + "  Line processing Resusts NOT Available." + endFont +"<br>";

    if(triang3DReady==3)
        status += greenFont + "  3D Points Available." + endFont;
    else
        status += redFont + "  3D Points NOT Available." +endFont;
    ui->label_EventProcessing->setText(status);


    if( lineProcReady==3 && triang3DReady==3) return true;
    else return false;

}


// Set Menu items to call their pushbutton counterparts
void MainWindow::on_actionProject_Settings_triggered()
{
    on_pushButton_ProjSettings_clicked();
}

void MainWindow::on_actionCalibrate_Cameras_triggered()
{
    on_pushButton_CameraCalibrate_clicked();
}

void MainWindow::on_actionSet_Reference_Targets_triggered()
{
    on_pushButton_RefTargets_clicked();
}

void MainWindow::on_actionTest_Event_Capture_triggered()
{
    on_pushButton_TestEvent_clicked();
}

void MainWindow::on_actionEvent_Processing_triggered()
{
    on_pushButton_ProcessVideo_clicked();
}

void MainWindow::on_actionReview_Results_triggered()
{
    on_pushButton_ReviewResults_clicked();
}

void MainWindow::on_actionExit_triggered()
{
//    if(QMessageBox::Yes==QMessageBox::question(this, "Exit Application?" ,"Exit Application?", QMessageBox::Yes,QMessageBox::No) )
        MainWindow::close();

}

void MainWindow::closeEvent(QCloseEvent *event)
{
    if(QMessageBox::Yes==QMessageBox::question(this, "Exit Application?" ,"Exit Application?", QMessageBox::Yes,QMessageBox::No) )
        MainWindow::close();
    else
    event->ignore();
}

